
#include "spaceship.h"
#include "WeTime.h"
#include "WeInput.h"
#include "WeVirtualInput.h"
#include "WeShaderProg.h"
#include "WeMatrix4.h"
#include "WeTexture2D.h"
#include "WeImage.h"
#include "WeMath.h"

using namespace WackiEngine;


SpaceShip::SpaceShip()
:_maxVel(350.0f), _ship("awing_sprite.png"), _laserIndex(0), _shooting(false)
{
}


void SpaceShip::setupInput()
{
	// connect input
	gVirtualInput().bindAxis("MoveUp", this, &SpaceShip::onMoveUp);
	gVirtualInput().bindAxis("MoveRight", this, &SpaceShip::onMoveRight);
	gVirtualInput().bindAxis("LookUp", this, &SpaceShip::onLookUp);
	gVirtualInput().bindAxis("LookRight", this, &SpaceShip::onLookRight);
	gVirtualInput().bindAction("Shoot", KE_Press, this, &SpaceShip::onShootStart);
	gVirtualInput().bindAction("Shoot", KE_Release, this, &SpaceShip::onShootStop);
}

void SpaceShip::onMoveUp(float value, uint32 deviceId)
{
	_acc.y = value;
}
void SpaceShip::onMoveRight(float value, uint32 deviceId)
{
	_acc.x = value;
}
void SpaceShip::onLookUp(float value, uint32 deviceId)
{
	_dir.y = value;
}
void SpaceShip::onLookRight(float value, uint32 deviceId)
{
	_dir.x = value;
}
void SpaceShip::onShootStart(uint32 deviceId)
{
	_shooting = true;
}

void SpaceShip::onShootStop(uint32 deviceId)
{
	_shooting = false;
}
void SpaceShip::shoot()
{
	static double lastFire = 0.0;
	lastFire += gTime().getFrameDelta();

	if(!_shooting)
		return;

	// yea if we did it propperly the lasers would be children to the spaceship node
	// and just fly in the forward dir and be rotate by the spaceships orientation
	// but we didn't and I don't want to spend too much time here
	// redo this when we have the scene graph finished...

	if(lastFire < 0.2) {
		return;
	}

	lastFire = 0.0;

	Vector4f leftPos(-Vector2f(28.0f, 0.0f));
	Vector4f rightPos(Vector2f(28.0f, 0.0f));

	Vector3f perp;
	perp = Vector3f(0.0f, 0.0f, 1.0f).cross(Vector3f(_dir));

	Matrix4f rot(
		-perp.x, -perp.y, 0.0f, _pos.x,
		-_dir.x, -_dir.y, 0.0f, _pos.y,
		0.0f, 0.0f, 1.0f, 0.0f,
		0.0f, 0.0f, 0.0f, 1.0f);

	leftPos = rot * leftPos;
	rightPos = rot * rightPos;

	_lasers[_laserIndex++].set(Vector2f(leftPos.x, leftPos.y), _dir, 1000.0f);
	_laserIndex %= 50;
	_lasers[_laserIndex++].set(Vector2f(rightPos.x, rightPos.y), _dir, 1000.0f);
	_laserIndex %= 50;

}

void SpaceShip::update()
{
	float delta = gTime().getFrameDelta();
	
	// calc new velocity
	_vel += _acc * delta * 2000.0f;

	if(_vel.length() > _maxVel)
		_vel = _vel.normalized() * _maxVel;

	_pos += _vel * delta;


	// calc new direction
	static Vector2f prevDir(1.0f, 0.0f);

	if(_dir.lengthSq() > 0.0f) {
		_dir.normalize();
		prevDir = _dir;
	}
	else
		_dir = prevDir;

	// shoot
	shoot();

	// move the ship sprite and rotate it correctly
	_ship.setDir(_dir);
	_ship.setPos(_pos);

	// manage the laser list
	for(auto& laser : _lasers) {
		if(!laser.isExpired())
			laser.update();
	}
}

void SpaceShip::render()
{
	_ship.render();
	for(auto& laser : _lasers) {
		if(!laser.isExpired())
			laser.render();
	}
}